home *** CD-ROM | disk | FTP | other *** search
- /********************************************************/
- /* aprelay.c v1.2 */
- /* P.Toilon (zorthrax@id-net.fr) */
- /* 29/10/1998 IDNET - Nancy - FRANCE */
- /* This relay is released into the Public Domain */
- /* The original file 'aprelay.c' has 8141 bytes */
- /********************************************************/
-
- /*
- ** This relay is made for Apirc v1.1
- ** IT WILL NOT WORK ON PREVIOUS VERSIONS
- */
-
- #include <stdio.h>
- #include <netdb.h>
- #include <sys/time.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
-
- /* Change it to #undef UNIX if under Windows */
- #undef UNIX
- /* Max simultaneous users on the relay */
- #define MAXUSERS 128
-
- /* Local listener socket timeout in seconds */
- #define LCTIMEOUT 120
- /* Max length of negociation frame before connecting to remote */
- #define MAXFRAME 128
- /* Max length of each frame's field */
- #define MAXSE (MAXFRAME/2)
-
- /*
- ** Change CLASSIDENT to #define if :
- ** 1 - You want to have each user with a different username to
- ** avoid K-line on some servers.
- ** 2 - #define UNIX is set (and you are running a Unix/Linux OS)
- ** 3 - You can have root access and can set the aprelay file uid bit to root
- ** (under root, after each compilation, do a 'chmod u+s aprelay')
- ** On Windows OSes, you can run apidentd for this.
- */
- #ifdef UNIX
- #define CLASSIDENT
- #endif
-
- /*
- ** If CLASSIDENT is defined (see above), we set a range of UIDs
- ** that begin at FIRSTUID. For example if FIRSTUID = 3000 and
- ** MAXUSERS = 16, users will have 3000@yourmachine.com, 3001@
- ** yourmachine.com and so on until 3015.
- **
- ** As numbers could not be appreciated by some ircops, it's
- ** probably better to add corresponding login entries in
- ** /etc/passwd to get real names.
- **
- ** E.g.: Still with MAXUSERS = 16 and FIRSTUID = 3000, you
- ** should have to add 16 users on your system, from
- ** apircuser1 to apircuser16 with UIDs from 3000 to 3015
- ** (Full Name: "Untrusted chat user").
- **
- ** On RedHat 5.0 you should make : adduser -u 3000 apircuser1
- ** On Slackware, run adduser and follow the instructions.
- ** Do not edit directly /etc/passwd if shadow passwords are used.
- **
- ** Users will have apircuser1@yourmachine.com for example.
- ** If user addresses still remain with UID numbers, verify that
- ** the auth port 113 (identd) is reachable from outside.
- */
- #ifdef CLASSIDENT
- #define FIRSTUID 3000
- #define LASTUID (MAXUSERS+FIRSTUID-1)
- #endif
-
- struct usr
- {
- int fd;
- int fdo;
- } usr[MAXUSERS];
-
- fd_set rfds,fds;
- long uip[MAXUSERS];
- struct sockaddr_in uin;
- short eoframe[MAXUSERS];
- int FIRST,mfd,maxfd,osz;
- char hname[MAXUSERS][MAXFRAME];
- char cnick[MAXSE],cserv[MAXSE],cport[MAXSE];
- char oc[BUFSIZ],*arg,*strchr(),*inet_ntoa(),tmp[BUFSIZ];
-
- int open_remote_server_socket(server,port)
- char *server;
- int port;
- {
- int fd;
- struct hostent *rmt;
- struct sockaddr_in out;
-
- if((fd=socket(AF_INET,SOCK_STREAM,0))<0)
- return(-1);
-
- if(!(rmt=gethostbyname(server)))
- {
- close(fd);
- return(-1);
- }
-
- memcpy(&out.sin_addr,rmt->h_addr,rmt->h_length);
-
- out.sin_family=AF_INET;
- out.sin_port=htons(port);
-
- if(connect(fd,(struct sockaddr *)&out,sizeof out)<0)
- {
- close(fd);
- return(-1);
- }
-
- return(fd);
- }
-
- int open_listener_socket(port,maxusers,timeout)
- int port,maxusers,timeout;
- {
- time_t tvey;
- struct sockaddr_in in;
- int fd,rt,sz=sizeof(struct sockaddr_in);
-
- if((fd=socket(AF_INET,SOCK_STREAM,0))<0)
- return(-1);
-
- memset(&in,0,sz);
- in.sin_family=AF_INET;
- in.sin_addr.s_addr=INADDR_ANY;
- in.sin_port=htons(port);
-
- time(&tvey);
-
- while((rt=bind(fd,(struct sockaddr *)&in,sz))<0 && (time(0l)-tvey)<timeout)
- sleep(1);
-
- if(rt<0 || listen(fd,maxusers)<0)
- {
- close(fd);
- return(-1);
- }
-
- return(fd);
- }
-
- int sd(fd,str)
- int fd;
- char *str;
- {
- return(send(fd,str,strlen(str),0));
- }
-
- int getnewusernum()
- {
- int i;
-
- for(i=0;i<MAXUSERS;i++)
- if(usr[i].fd==-1)
- return(i);
- return(-1);
- }
-
- int getmaxfdvalue(fd)
- int fd;
- {
- int i,j;
-
- for(i=0,j=-1;i<MAXUSERS;i++)
- {
- if(usr[i].fd>j)
- j=usr[i].fd;
- if(usr[i].fdo>j)
- j=usr[i].fdo;
- }
-
- if(fd>j)
- j=fd;
-
- return(j);
- }
-
- /*
- ** accept sent a broken pipe (signal 13)
- ** We go back into accept_user()
- */
- void b_accept()
- {
- FIRST=0;
- accept_user();
- }
-
- accept_user()
- {
- char *pt1,*pt2;
- struct hostent *ht;
- int i,j,si[4],newfd;
-
- /*
- ** To avoid the accept() brokenpipe
- */
- signal(13,b_accept);
-
- if(FIRST)
- {
- for(i=0;i<MAXUSERS;i++)
- {
- usr[i].fd=-1;
- usr[i].fdo=-1;
- }
-
- FD_ZERO(&fds);
- FD_ZERO(&rfds);
- FD_SET((maxfd=mfd),&fds);
- }
-
- while(1)
- {
- rfds=fds;
- select(maxfd+1,&rfds,NULL,NULL,0);
-
- if(FD_ISSET(mfd,&rfds))
- {
- if((newfd=accept(mfd,(struct sockaddr *)&uin,&osz))>=0)
- {
- /*
- ** IP Filtering. E.g: 'arg="192.168";' will
- ** forbid all 192.168.x.x IP addresses.
- */
- //arg="192.168.0.43";
- if(arg && !strncmp(arg,inet_ntoa(uin.sin_addr.s_addr),strlen(arg)))
- {
- sd(newfd,"Sorry, your host is not allowed !\n\r");
- close(newfd);
- }
- else if((i=getnewusernum())==-1)
- {
- sd(newfd,"Sorry, all relay sockets are busy !\n\r");
- close(newfd);
- }
- else
- {
- usr[i].fd=newfd;
- usr[i].fdo=-1;
- eoframe[i]=0;
- sd(usr[i].fd,"Apirc relay v1.2\r\n\n");
- if(!(ht=gethostbyaddr((char *)&uin.sin_addr,sizeof(unsigned long),AF_INET)))
- strcpy(hname[i],inet_ntoa(uin.sin_addr.s_addr));
- else
- strcpy(hname[i],ht->h_name);
- FD_SET(usr[i].fd,&fds);
- maxfd=getmaxfdvalue(mfd);
- }
- }
- }
- else for(i=0;i<MAXUSERS;i++)
- {
- if(usr[i].fd!=-1 && FD_ISSET(usr[i].fd,&rfds))
- {
- if(!(j=recv(usr[i].fd,oc,BUFSIZ,0))) /* If disconnected */
- {
- FD_CLR(usr[i].fd,&fds);
- close(usr[i].fd);
- usr[i].fd=-1;
- if(usr[i].fdo!=-1)
- {
- FD_CLR(usr[i].fdo,&fds);
- close(usr[i].fdo);
- usr[i].fdo=-1;
- }
- maxfd=getmaxfdvalue(mfd);
- }
- else if(usr[i].fdo!=-1) /* connected to remote serv */
- send(usr[i].fdo,oc,j,0);
- else if(!eoframe[i])
- {
- /* too big negociation frame */
- if(j>=MAXFRAME)
- {
- FD_CLR(usr[i].fd,&fds);
- close(usr[i].fd);
- usr[i].fd=-1;
- maxfd=getmaxfdvalue(mfd);
- }
- else if(j>4 && strchr(oc,'º')) /* "MyNick:irc.id-net.fr:6667:º" */
- {
- pt1=oc;
- *(pt2=strchr(pt1,':'))='\0';
- strcpy(cnick,pt1);
- pt1=pt2+1;
- *(pt2=strchr(pt1,':'))='\0';
- strcpy(cserv,pt1);
- pt1=pt2+1;
- *(pt2=strchr(pt1,':'))='\0';
- strcpy(cport,pt1);
- eoframe[i]=1;
- }
- }
- else /* We just received the complete frame, let's connect */
- {
- #ifdef CLASSIDENT
- setreuid(FIRSTUID+i,NULL);
- #endif
- if((usr[i].fdo=open_remote_server_socket(cserv,atoi(cport)))<0)
- {
- sd(usr[i].fd,"Server unavailable\r\n");
- FD_CLR(usr[i].fd,&fds); /* On libere */
- close(usr[i].fd);
- usr[i].fd=-1;
- maxfd=getmaxfdvalue(mfd);
- }
- else
- {
- FD_SET(usr[i].fdo,&fds);
- maxfd=getmaxfdvalue(mfd);
- srand(time(0l));
- sprintf(tmp,"NICK %s\nUSER user%d host server :%s [Real user host]\n",cnick,rand()%9000+1000,hname[i]);
- sd(usr[i].fdo,tmp);
- send(usr[i].fdo,oc,j,0); /* 1st datas sent to th server */
- }
- }
- }
-
- if(usr[i].fdo!=-1 && FD_ISSET(usr[i].fdo,&rfds))
- {
- if(!(j=recv(usr[i].fdo,oc,BUFSIZ,0))) /* If disconnected */
- {
- FD_CLR(usr[i].fd,&fds);
- FD_CLR(usr[i].fdo,&fds);
- close(usr[i].fd);
- close(usr[i].fdo);
- usr[i].fd=-1;
- usr[i].fdo=-1;
- maxfd=getmaxfdvalue(mfd);
- }
- else
- send(usr[i].fd,oc,j,0);
- }
- }
- }
- }
-
- main(argc,argv)
- int argc;
- char **argv;
- {
- arg=(argc==2)?argv[1]:NULL;
-
- #ifdef CLASSIDENT
- if(getuid() && setuid(NULL)==-1)
- {
- printf("\nYou must set the binary file uid bit to root. Daemon not ready\n");
- exit();
- }
- #endif
-
- printf("Trying to open the listener socket ... ");
- fflush(stdout);
-
- if((mfd=open_listener_socket(8888,MAXUSERS,LCTIMEOUT))<0)
- {
- printf("\nSocket not openable. Daemon not ready\n");
- exit();
- }
-
- printf("\nListener socket ready\n");
- fflush(stdout);
-
- #ifdef UNIX
- if(fork())
- exit();
- #endif
-
- osz=sizeof(struct sockaddr_in);
- FIRST=1;
- accept_user();
- }
-